package com.heima.search.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.json.JsonData;
import com.heima.common.dtos.ResponseResult;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.search.vos.SearchArticleVo;
import com.heima.search.service.ArticleSearchService;
import io.netty.handler.codec.serialization.ObjectEncoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.BooleanQuery;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Queue;

@Slf4j
@Service
public class ArticleSearchServiceImpl implements ArticleSearchService {
    @Resource
    private ElasticsearchClient elasticsearchClient;

    private static final String INDEX_NAME = "app_info_article";

    @Override
    public ResponseResult<List<SearchArticleVo>> search(UserSearchDto userSearchDto) throws IOException {
        Query query = this.buildBasicQuery(userSearchDto);
        int size = userSearchDto.getPageSize();
        int from = userSearchDto.getFromIndex();
        //2. 搜索数据
        SearchResponse<SearchArticleVo> searchResponse = this.elasticsearchClient.search(builder -> builder
                        .index(INDEX_NAME)
                        .query(query) //设置查询条件
                        .from(from) //分页参数
                        .size(size) //分页参数
                        .sort(s -> s.field(f -> f.field("publishTime").order(SortOrder.Desc))) //按照发布时间倒序查询
                        .highlight(h -> h.fields("title", f -> f
                                .requireFieldMatch(false)
                                .preTags("<font style='color: red; font-size: inherit;'>")
                                .postTags("</font>"))) //设置标题高亮
                , SearchArticleVo.class);
        List<SearchArticleVo> searchArticleVos = CollStreamUtil.toList(searchResponse.hits().hits(), hit -> {
            SearchArticleVo source = hit.source();
            if (ObjectUtil.isNotEmpty(source)) {
                Map<String, List<String>> highlight = hit.highlight();
                if (ObjectUtil.isNotEmpty(highlight)) {
                    source.setH_title(StrUtil.join(",", highlight.get("title")));
                } else {
                    source.setH_title(source.getTitle());
                }
            }
            return source;
        });
        return ResponseResult.okResult(searchArticleVos);
    }

    private Query buildBasicQuery(UserSearchDto dto) {
        BoolQuery.Builder booleanQuery = new BoolQuery.Builder();

        if (ObjectUtil.isEmpty(dto.getSearchWords())) {
            booleanQuery.must(m -> m.matchAll(builder -> builder));
        } else {
            booleanQuery.must(m -> m.match(ma -> ma.field("all").query(dto.getSearchWords())));
        }

        if (ObjectUtil.isNotEmpty(dto.getMinBehotTime())) {
            booleanQuery.filter(builder -> builder.range(r -> r.field("publishTime").lt(JsonData.of(dto.getMinBehotTime()))));
        }
        return new Query.Builder()
                .bool(booleanQuery.build())
                .build();

    }
}
